----------------------------------------------------------------
-- Local variables
----------------------------------------------------------------
EA_Window_InteractionRenownTraining =
{
    advanceData      = nil,
    delayedRefresh   = true,
    
    selectedAdvances = {},
    pointsSpent      = 0,
    
    ANCHOR_CURSOR    = { Point = "topleft", RelativeTo = "CursorWindow", RelativePoint = "bottomleft", XOffset = 30, YOffset = -20 },

    TIER_COUNT       = 3,
    
    tiers = { {requiredPoints = 0,  },
              {requiredPoints = 20, },
              {requiredPoints = 40, }, },
}


----------------------------------------------------------------
-- Standard Window Functions
----------------------------------------------------------------
function EA_Window_InteractionRenownTraining.Initialize()

    EA_Window_InteractionRenownTraining.InitializeLabels()
    EA_Window_InteractionRenownTraining.UpdatePlayerResources()

    -- register event handlers
    WindowRegisterEventHandler("EA_Window_InteractionRenownTraining", SystemData.Events.PLAYER_CAREER_CATEGORY_UPDATED,  "EA_Window_InteractionRenownTraining.FullRefresh")
    WindowRegisterEventHandler("EA_Window_InteractionRenownTraining", SystemData.Events.PLAYER_MONEY_UPDATED,            "EA_Window_InteractionRenownTraining.UpdatePlayerResources" )
    WindowRegisterEventHandler("EA_Window_InteractionRenownTraining", SystemData.Events.PLAYER_ABILITIES_LIST_UPDATED,   "EA_Window_InteractionRenownTraining.Refresh" )
    WindowRegisterEventHandler("EA_Window_InteractionRenownTraining", SystemData.Events.PLAYER_SINGLE_ABILITY_UPDATED,   "EA_Window_InteractionRenownTraining.Refresh" )
end

function EA_Window_InteractionRenownTraining.Shutdown()

    for _, advanceFrame in pairs(EA_Window_InteractionRenownTrainingLayout.frames)
    do
        for frameIndex = advanceFrame:Begin(), 
                         advanceFrame:End()
        do
            advanceFrame[frameIndex]:Destroy()
        end
        advanceFrame:Clear()
    end
    
    EA_Window_InteractionRenownTraining.advanceData = nil
end

function EA_Window_InteractionRenownTraining.OnShown()
    WindowUtils.OnShown(EA_Window_InteractionRenownTraining.Hide, WindowUtils.Cascade.MODE_AUTOMATIC)
end

function EA_Window_InteractionRenownTraining.OnHidden()
    WindowUtils.RemoveFromOpenList("EA_Window_InteractionRenownTraining")
end

function EA_Window_InteractionRenownTraining.ToggleContextMenu()
end

function EA_Window_InteractionRenownTraining.Show()
    WindowSetShowing( "EA_Window_InteractionRenownTraining", true )
    
    if (EA_Window_InteractionRenownTraining.advanceData == nil) or
       (EA_Window_InteractionRenownTraining.delayedRefresh == true)
    then
        EA_Window_InteractionRenownTraining.Refresh()
    else
        EA_Window_InteractionRenownTraining.UpdatePlayerResources()
        EA_Window_InteractionRenownTrainingLayout.RefreshStates()
    end
end

function EA_Window_InteractionRenownTraining.Hide()
    WindowSetShowing( "EA_Window_InteractionRenownTraining", false )
    
    EA_Window_InteractionRenownTraining.selectedAdvances = {}
    EA_Window_InteractionRenownTraining.pointsSpent      = 0
    EA_Window_InteractionRenownTrainingLayout.ResetPurchases()
end

function EA_Window_InteractionRenownTraining.Refresh()
    if (WindowGetShowing("EA_Window_InteractionRenownTraining"))
    then
        EA_Window_InteractionRenownTraining.LoadAdvances()
        EA_Window_InteractionRenownTrainingLayout.FillTiers(EA_Window_InteractionRenownTraining.advanceData)
        EA_Window_InteractionRenownTrainingLayout.LayoutTiers()
        EA_Window_InteractionRenownTrainingLayout.RefreshStates()
        EA_Window_InteractionRenownTraining.UpdatePlayerResources()
        EA_Window_InteractionRenownTraining.delayedRefresh = false
    else
        EA_Window_InteractionRenownTraining.delayedRefresh = true
    end
end

function EA_Window_InteractionRenownTraining.FullRefresh()
    -- Clear the selected advances and then refresh
    EA_Window_InteractionRenownTraining.selectedAdvances = {}
    EA_Window_InteractionRenownTraining.pointsSpent      = 0
    EA_Window_InteractionRenownTrainingLayout.ResetPurchases()
    EA_Window_InteractionRenownTraining.Refresh()
end

----------------------------------------------------------------
-- Money/resource/display initialization and updates
----------------------------------------------------------------
function EA_Window_InteractionRenownTraining.UpdatePlayerResources()
    local pointsRemaining = EA_Window_InteractionRenownTraining.GetPointsAvailable()
    local pointsSpent     = EA_Window_InteractionRenownTraining.GetPointsSpent()
    local pointText       = GetStringFormatFromTable("TrainingStrings", StringTables.Training.LABEL_RENOWN_POINTS_LEFT, { L""..pointsRemaining } )

    LabelSetText("EA_Window_InteractionRenownTrainingPurseLabel", pointText)

    LabelSetText("EA_Window_InteractionRenownTrainingMainScrollChildTierArrow2GateLabel", GetStringFormatFromTable("TrainingStrings", StringTables.Training.LABEL_RENOWN_GATE, { L""..pointsSpent, L""..EA_Window_InteractionRenownTraining.tiers[2].requiredPoints } ) )
    LabelSetText("EA_Window_InteractionRenownTrainingMainScrollChildTierArrow3GateLabel", GetStringFormatFromTable("TrainingStrings", StringTables.Training.LABEL_RENOWN_GATE, { L""..pointsSpent, L""..EA_Window_InteractionRenownTraining.tiers[3].requiredPoints } ) )
    
    WindowSetShowing("EA_Window_InteractionRenownTrainingMainScrollChildTierArrow2Green",     (pointsSpent >= EA_Window_InteractionRenownTraining.tiers[2].requiredPoints))
    WindowSetShowing("EA_Window_InteractionRenownTrainingMainScrollChildTierArrow2Red",   not (pointsSpent >= EA_Window_InteractionRenownTraining.tiers[2].requiredPoints))
    WindowSetShowing("EA_Window_InteractionRenownTrainingMainScrollChildTierArrow3Green",     (pointsSpent >= EA_Window_InteractionRenownTraining.tiers[3].requiredPoints))
    WindowSetShowing("EA_Window_InteractionRenownTrainingMainScrollChildTierArrow3Red",   not (pointsSpent >= EA_Window_InteractionRenownTraining.tiers[3].requiredPoints))
end

function EA_Window_InteractionRenownTraining.GetHighestUnlockedTier()
    local pointsSpent = EA_Window_InteractionRenownTraining.GetPointsSpent()

    local unlockedTier = 0
    for tier = 1, EA_Window_InteractionRenownTraining.TIER_COUNT
    do
        if (pointsSpent >= EA_Window_InteractionRenownTraining.tiers[tier].requiredPoints)
        then
            unlockedTier = tier
        end
    end

    return unlockedTier
end

function EA_Window_InteractionRenownTraining.InitializeLabels()
    LabelSetText("EA_Window_InteractionRenownTrainingTitleBarText",         GetStringFromTable("TrainingStrings", StringTables.Training.LABEL_RENOWN_TRAINING_TITLE ) )
    LabelSetText("EA_Window_InteractionRenownTrainingMainScrollChildHint",  GetStringFromTable("TrainingStrings", StringTables.Training.HINT_SELECT_TO_PURCHASE) )

    -- Gate level hint text
    LabelSetText("EA_Window_InteractionRenownTrainingMainScrollChildTierArrow2GateHint", GetStringFormatFromTable("TrainingStrings", StringTables.Training.TEXT_RENOWN_GATE_HINT, { L""..EA_Window_InteractionRenownTraining.tiers[2].requiredPoints }) )
    LabelSetText("EA_Window_InteractionRenownTrainingMainScrollChildTierArrow3GateHint", GetStringFormatFromTable("TrainingStrings", StringTables.Training.TEXT_RENOWN_GATE_HINT, { L""..EA_Window_InteractionRenownTraining.tiers[3].requiredPoints }) )

    -- Footer buttons
    ButtonSetText( "EA_Window_InteractionRenownTrainingRespecializeButton", GetString( StringTables.Default.LABEL_PURCHASE_RESPECIALIZATION ) )
    ButtonSetText( "EA_Window_InteractionRenownTrainingPurchaseButton",     GetStringFromTable("TrainingStrings", StringTables.Training.LABEL_PURCHASE_TRAINING ) )
    ButtonSetText( "EA_Window_InteractionRenownTrainingCancelButton",       GetStringFromTable("TrainingStrings", StringTables.Training.LABEL_CANCEL_TRAINING ) )
end

----------------------------------------------------------------
-- Data Population
----------------------------------------------------------------
function EA_Window_InteractionRenownTraining.LoadAdvances()
    EA_Window_InteractionRenownTraining.advanceData = GameData.Player.GetAdvanceData()
end

----------------------------------------------------------------
-- Respecialize
----------------------------------------------------------------
function EA_Window_InteractionRenownTraining.Respecialize()
    local respecCost = GameData.Player.GetRenownRefundCost()
    local pointsSpent = EA_Window_InteractionRenownTraining.GetPointsAlreadyPurchased()
    
    if (pointsSpent == 0)
    then
        -- There are no points to refund. In this case this button acts as a simple Reset.
        EA_Window_InteractionRenownTraining.FullRefresh()
    elseif (respecCost > GameData.Player.money)
    then
        DialogManager.MakeOneButtonDialog( GetStringFormatFromTable("TrainingStrings", StringTables.Training.TEXT_RESPEC_NOT_ENOUGH_MONEY, { MoneyFrame.FormatMoneyString (respecCost) }),
                                           GetString( StringTables.Default.LABEL_OKAY ), nil )
    else
        DialogManager.MakeTwoButtonDialog( GetStringFormatFromTable("TrainingStrings", StringTables.Training.TEXT_RESPEC_CONFIRMATION, { MoneyFrame.FormatMoneyString (respecCost) }), 
                                           GetString(StringTables.Default.LABEL_YES), RefundRenownPoints, 
                                           GetString(StringTables.Default.LABEL_NO) )
    end
end

----------------------------------------------------------------
-- Advance purchase
----------------------------------------------------------------
function EA_Window_InteractionRenownTraining.PurchaseAdvances()
    if (ButtonGetDisabledFlag("EA_Window_InteractionRenownTrainingPurchaseButton") == false)
    then
        for dataIndex, isSelected in pairs(EA_Window_InteractionRenownTraining.selectedAdvances)
        do
            if (isSelected)
            then
                local advanceData  = EA_Window_InteractionRenownTraining.selectedAdvances[dataIndex]
                local packageID    = advanceData.packageId
                local tier         = advanceData.tier
                local category     = advanceData.category
                -- DEBUG(L"  BuyCareerPackage( "..tier..L", "..category..L", "..packageID..L" )")
                BuyCareerPackage( tier, category, packageID )
            end
        end
        
        -- (assume the purchase worked?)
        EA_Window_InteractionRenownTraining.selectedAdvances = {}
        EA_Window_InteractionRenownTraining.pointsSpent      = 0

        PlayInteractSound("trainer_accept")
    end
end

function EA_Window_InteractionRenownTraining.SelectRenownAbility()

    local selectedFrame = FrameManager:GetMouseOverWindow()
    
    if (selectedFrame:IsSelected())
    then
        selectedFrame:Decrement()
    elseif (selectedFrame:IsSelectable())
    then
        selectedFrame:Increment()
    else
        -- Do nothing.
    end

end

function EA_Window_InteractionRenownTraining.SelectRenownPassive()
    local selectedFrame = FrameManager:GetMouseOverWindow()
    
    if ((selectedFrame ~= nil) and selectedFrame:IsSelectable())
    then
        selectedFrame:Increment()
    end
end

function EA_Window_InteractionRenownTraining.DeselectRenownPassive()
    local selectedFrame = FrameManager:GetMouseOverWindow()

    if ((selectedFrame ~= nil) and selectedFrame:IsDeselectable())
    then
        selectedFrame:Decrement()
    end
end

function EA_Window_InteractionRenownTraining.MouseOverRenownAdvance()
    local selectedFrame = FrameManager:GetMouseOverWindow()

    if (selectedFrame)
    then
        local advanceData = selectedFrame:GetAdvanceData()
        local abilityData = advanceData.abilityInfo
        
        local priceString = GetStringFormatFromTable("TrainingStrings", StringTables.Training.TEXT_RENOWN_POINT_COST, { L""..advanceData.pointCost } )

        if (abilityData ~= nil)
        then            
            -- Move package limit to ability level
            abilityData["minimumRank"] = advanceData.minimumRank
            
            -- DUMP_TABLE(abilityData)
            Tooltips.CreateAbilityTooltip( abilityData, SystemData.ActiveWindow.name, EA_Window_InteractionRenownTraining.ANCHOR_CURSOR, priceString )
            Tooltips.SetUpdateCallback(EA_Window_InteractionRenownTraining.UpdateAdvanceTooltip)
        else
            -- This isn't an ability so look up the relevent package tooltip.
            Tooltips.CreateTextOnlyTooltip(SystemData.ActiveWindow.name)

            Tooltips.SetTooltipText( 1, 1, advanceData.advanceName )
            Tooltips.SetTooltipColorDef( 1, 1, Tooltips.COLOR_HEADING )
            Tooltips.SetTooltipText( 2, 1, GetStringFromTable( "PackageDescriptions", advanceData.advanceID ) )
            Tooltips.SetTooltipText( 3, 1, priceString )
            Tooltips.SetUpdateCallback(EA_Window_InteractionRenownTraining.UpdateAdvanceTooltip)
            Tooltips.Finalize()

            Tooltips.AnchorTooltip( EA_Window_InteractionRenownTraining.ANCHOR_CURSOR ) 
        end
    end

end

function EA_Window_InteractionRenownTraining.UpdateAdvanceTooltip()
    local selectedFrame = FrameManager:GetMouseOverWindow()

    if (selectedFrame)
    then
        local advanceData = selectedFrame:GetAdvanceData()
        local abilityData = advanceData.abilityInfo
        
        local priceString = GetStringFormatFromTable("TrainingStrings", StringTables.Training.TEXT_RENOWN_POINT_COST, { L""..advanceData.pointCost } )

        if (abilityData ~= nil)
        then            
            -- Move package limit to ability level
            abilityData["minimumRank"] = advanceData.minimumRank
        else
            -- This isn't an ability so look up the relevent package tooltip.
            Tooltips.SetTooltipText( 1, 1, advanceData.advanceName )
            Tooltips.SetTooltipText( 2, 1, GetStringFromTable( "PackageDescriptions", advanceData.advanceID ) )
            Tooltips.SetTooltipText( 3, 1, priceString )
            Tooltips.Finalize()
        end
    end
end

-- This function simulates what we think the server will do if we were to hit the 'buy all these packages' button
--   at the present.
function EA_Window_InteractionRenownTraining.SimulatePurchase()

    local isAnySelected = false
    local totalCost     = 0
    
    for dataIndex, isSelected in pairs(EA_Window_InteractionRenownTraining.selectedAdvances)
    do
        isAnySelected = isAnySelected or isSelected
        
        local advanceData = EA_Window_InteractionRenownTraining.advanceData[dataIndex]
        totalCost = totalCost + advanceData.cashCost
    end
    
    local sufficientCash = totalCost <= Player.GetMoney()

    return isAnySelected and sufficientCash
end

----------------------------------------------------------------
-- Utiltiy Functions
----------------------------------------------------------------
function EA_Window_InteractionRenownTraining.GetPointsAvailable()
    local pointsTotal     = GameData.Player.GetAdvancePointsAvailable()[GameData.CareerCategory.RENOWN_STATS_A]
    local pointsSpent     = EA_Window_InteractionRenownTraining.pointsSpent
    local pointsRemaining = pointsTotal - pointsSpent
    
    return pointsRemaining
end

function EA_Window_InteractionRenownTraining.GetPointsAlreadyPurchased()
    -- loop through and take the highest of any of category 9-15, since only the most recently updated will
    --   contain an accurate number
    local purchasedPoints   = GameData.Player.GetAdvancePointsSpent()
    local purchasedPointsMaximum = 0
    for category = GameData.CareerCategory.RENOWN_STATS_A, GameData.CareerCategory.RENOWN_REALM
    do
        purchasedPointsMaximum = math.max(purchasedPointsMaximum, purchasedPoints[category])
    end
    return purchasedPointsMaximum
end

function EA_Window_InteractionRenownTraining.GetPointsSpent()
    local purchasedPoints   = EA_Window_InteractionRenownTraining.GetPointsAlreadyPurchased()
    local speculativePoints = EA_Window_InteractionRenownTraining.pointsSpent
    local spentTotal        = purchasedPoints + speculativePoints
    
    return spentTotal
end


----------------------------------------------------------------
-- Button Grid Layout Manager
----------------------------------------------------------------
EA_Window_InteractionRenownTrainingLayout =
{
    frames    = { Queue:Create(), Queue:Create(), Queue:Create() },
    passives  = { {},             {},             {}             },
    abilities = { Queue:Create(), Queue:Create(), Queue:Create() },
}

function EA_Window_InteractionRenownTrainingLayout.DetermineButtonPosition(tier, index)

    -- Three tiers, twenty entries each arranged 7 / 6 / 7.
    local x = 40
    local y = 40
    
    local ICON_WIDTH  = 66
    local ICON_HEIGHT = 61
    -- assuming windows are sized as above
    local row = 0

    if (index > 19)
    then
        ERROR(L"Too many entries in this tier")
        return EA_Window_InteractionRenownTrainingLayout.DetermineButtonPosition(tier + 1, index - 20)
    elseif (index > 12)
    then
        row = 2
        x = x + (index - 13) * ICON_WIDTH
    elseif (index > 6)
    then
        row = 1
        x = x + ((index - 7) * ICON_WIDTH) + (ICON_WIDTH / 2)
    else
        row = 0
        x = x + (index) * ICON_WIDTH
    end
    
    y = y + ((tier - 1) * ((ICON_HEIGHT * 3) + 84)) + (row * ICON_HEIGHT)
     
    return x, y

end

function EA_Window_InteractionRenownTrainingLayout.FillTiers(advanceList)

    for tier = 1, EA_Window_InteractionRenownTraining.TIER_COUNT
    do
        EA_Window_InteractionRenownTrainingLayout.abilities[tier]:Clear()
        EA_Window_InteractionRenownTrainingLayout.passives[tier] = {}
    end
    
    for _, advanceData in ipairs(advanceList)
    do
        local advanceTier = 0
        for tier = EA_Window_InteractionRenownTraining.TIER_COUNT, 1, -1
        do
            if (advanceData.minimumCategoryPoints == EA_Window_InteractionRenownTraining.tiers[tier].requiredPoints)
            then
                advanceTier = tier
                break
            end
        end
        
        if (InteractionUtils.IsRenownAdvance(advanceData))
        then
            -- push to the correct tier, just pile everything into one for now
            if (InteractionUtils.IsTactic(advanceData))
            then
                EA_Window_InteractionRenownTrainingLayout.abilities[advanceTier]:PushBack(advanceData)
            else
                -- Since these have mostly unique icons, use this as a key to lump together similar
                -- advances.  This breaks if advances which are not in the 'advance chain' share
                -- the same icon and a similar name.
                local passiveKey = {}
                if (advanceData.abilityInfo == nil)
                then
                    passiveKey = (advanceData.advanceIcon * 256) + 
                                  wstring.byte( advanceData.advanceName, 1 )
                else
                    passiveKey = (advanceData.abilityInfo.iconNum * 256) + 
                                  wstring.byte( advanceData.abilityInfo.name, 1 )
                end
                
                if (EA_Window_InteractionRenownTrainingLayout.passives[advanceTier][passiveKey] == nil)
                then
                    EA_Window_InteractionRenownTrainingLayout.passives[advanceTier][passiveKey] = {}
                end
                
                table.insert(EA_Window_InteractionRenownTrainingLayout.passives[advanceTier][passiveKey], advanceData)
            end
        end
    end
end

function EA_Window_InteractionRenownTrainingLayout.ClearTiers()
    for tier = 1, EA_Window_InteractionRenownTraining.TIER_COUNT
    do
        EA_Window_InteractionRenownTrainingLayout.abilities[tier]:Clear()
        EA_Window_InteractionRenownTrainingLayout.passives[tier] = {}

        for frameIndex = EA_Window_InteractionRenownTrainingLayout.frames[tier]:Begin(), 
                         EA_Window_InteractionRenownTrainingLayout.frames[tier]:End()
        do
            EA_Window_InteractionRenownTrainingLayout.frames[tier][frameIndex]:Destroy()
        end

        EA_Window_InteractionRenownTrainingLayout.frames[tier]:Clear()
    end
end

function EA_Window_InteractionRenownTrainingLayout.LayoutTiers()
    for tier = 1, EA_Window_InteractionRenownTraining.TIER_COUNT
    do
        EA_Window_InteractionRenownTrainingLayout.LayoutTier(tier)
    end
end

function EA_Window_InteractionRenownTrainingLayout.LayoutTier(tierNumber)
    -- All Stat packages followed by all tactics within a tier
    local passivesCount = 0
    for _, advancesTable in pairs(EA_Window_InteractionRenownTrainingLayout.passives[tierNumber])
    do
        local passiveFrame = EA_Window_InteractionRenownPassive:Create( "EA_Window_InteractionRenownTrainingAdvanceItem"..tierNumber.."-"..passivesCount,
                                                                        "EA_Window_InteractionRenownTrainingMainScrollChild",
                                                                        advancesTable)
        EA_Window_InteractionRenownTrainingLayout.frames[tierNumber]:PushBack(passiveFrame)
        
        local x, y = EA_Window_InteractionRenownTrainingLayout.DetermineButtonPosition(tierNumber, passivesCount)
        -- DEBUG(L"  Positioning tactic frame #"..passiveIndex..L" at "..x..L", "..y)
        WindowClearAnchors( passiveFrame:GetName() )
        WindowSetOffsetFromParent( passiveFrame:GetName(), x, y )
        WindowSetShowing( passiveFrame:GetName(), true )
        
        passivesCount = passivesCount + 1
    end
    
    for abilityIndex = EA_Window_InteractionRenownTrainingLayout.abilities[tierNumber]:Begin(),
                       EA_Window_InteractionRenownTrainingLayout.abilities[tierNumber]:End()
    do
        local advanceData  = EA_Window_InteractionRenownTrainingLayout.abilities[tierNumber][abilityIndex]
        local frameCount   = passivesCount + abilityIndex
        local abilityFrame = EA_Window_InteractionRenownTacticAbility:Create( "EA_Window_InteractionRenownTrainingAdvanceItem"..tierNumber.."-"..frameCount,
                                                                              "EA_Window_InteractionRenownTrainingMainScrollChild",
                                                                              advanceData)
        EA_Window_InteractionRenownTrainingLayout.frames[tierNumber]:PushBack(abilityFrame)
        
        local x, y = EA_Window_InteractionRenownTrainingLayout.DetermineButtonPosition(tierNumber, frameCount)
        -- DEBUG(L"  Positioning tactic frame #"..abilityIndex..L" at "..x..L", "..y)
        WindowClearAnchors( abilityFrame:GetName() )
        WindowSetOffsetFromParent( abilityFrame:GetName(), x, y )
        WindowSetShowing( abilityFrame:GetName(), true )
    end
    
    -- EA_Window_InteractionRenownTrainingLayout.abilities[tierNumber]:Clear()
end

function EA_Window_InteractionRenownTrainingLayout.RefreshStates()
    local pointsRemaining = EA_Window_InteractionRenownTraining.GetPointsAvailable()
    local pointsSpent     = EA_Window_InteractionRenownTraining.GetPointsSpent()
    
    for tierIndex = 1,3
    do
        for frameIndex = EA_Window_InteractionRenownTrainingLayout.frames[tierIndex]:Begin(),
                         EA_Window_InteractionRenownTrainingLayout.frames[tierIndex]:End()
        do
            local advanceFrame    = EA_Window_InteractionRenownTrainingLayout.frames[tierIndex][frameIndex]
            advanceFrame:UpdateState(pointsRemaining, pointsSpent)
        end
    end
end

function EA_Window_InteractionRenownTrainingLayout.ResetPurchases()
    for tierIndex = 1,3
    do
        for frameIndex = EA_Window_InteractionRenownTrainingLayout.frames[tierIndex]:Begin(),
                         EA_Window_InteractionRenownTrainingLayout.frames[tierIndex]:End()
        do
            local advanceFrame = EA_Window_InteractionRenownTrainingLayout.frames[tierIndex][frameIndex]
            advanceFrame:Reset()
        end
    end
end

----------------------------------------------------------------
-- Renown Tactic Abilities Button Class
----------------------------------------------------------------
EA_Window_InteractionRenownTacticAbility = Frame:Subclass("EA_Templates_RenownAbility")

function EA_Window_InteractionRenownTacticAbility:Create(windowName, parentName, advanceData)
    -- DEBUG(L"  Creating tactic frame "..StringToWString(windowName))
    
    local abilityFrame
    if (DoesWindowExist(windowName))
    then
        abilityFrame = FrameManager:Get(windowName)
    else
        abilityFrame = self:CreateFromTemplate(windowName, parentName)
    end
    
    if (abilityFrame ~= nil)
    then
        abilityFrame.m_AdvanceData     = advanceData
        abilityFrame.m_SelectionCount  = advanceData.timesPurchased
    end
    
    local texture, x, y = GetIconData(advanceData.abilityInfo.iconNum)
    DynamicImageSetTexture( windowName.."Icon", texture, x, y )
    
    return abilityFrame
end

function EA_Window_InteractionRenownTacticAbility:Reset()
    self.m_SelectionCount = self:GetAdvanceData().timesPurchased
end

function EA_Window_InteractionRenownTacticAbility:SetPurchased()
    ButtonSetDisabledFlag( self:GetName(), true )
    ButtonSetCheckButtonFlag( self:GetName(), false )
    ButtonSetStayDownFlag( self:GetName(), true )
    ButtonSetPressedFlag( self:GetName(), true )

    local color = DefaultColor.RowColors.SELECTED
    WindowSetTintColor( self:GetName().."Icon", color.r, color.g, color.b )
end

function EA_Window_InteractionRenownTacticAbility:SetAvailable()
    ButtonSetDisabledFlag( self:GetName(), false )
    ButtonSetCheckButtonFlag( self:GetName(), true )
    ButtonSetStayDownFlag( self:GetName(), false )
    ButtonSetPressedFlag( self:GetName(), false )

    local color = DefaultColor.RowColors.AVAILABLE
    WindowSetTintColor( self:GetName().."Icon", color.r, color.g, color.b )
end

function EA_Window_InteractionRenownTacticAbility:SetSelected()
    ButtonSetDisabledFlag( self:GetName(), false )
    ButtonSetCheckButtonFlag( self:GetName(), true )
    ButtonSetStayDownFlag( self:GetName(), false )
    ButtonSetPressedFlag( self:GetName(), true )

    local color = DefaultColor.RowColors.SELECTED
    WindowSetTintColor( self:GetName().."Icon", color.r, color.g, color.b )
end

function EA_Window_InteractionRenownTacticAbility:SetUnavailable()
    ButtonSetDisabledFlag( self:GetName(), true )
    ButtonSetPressedFlag( self:GetName(), false )
    
    local color = DefaultColor.RowColors.UNAVAILABLE
    WindowSetTintColor( self:GetName().."Icon", color.r, color.g, color.b )
end

function EA_Window_InteractionRenownTacticAbility:SetIcon()
    local texture, x, y = GetIconData(self.m_AdvanceData.abilityInfo.iconNum)
    DynamicImageSetTexture(self:GetName().."Icon", texture, x, y)
end

function EA_Window_InteractionRenownTacticAbility:GetAdvanceData()
    return self.m_AdvanceData
end

function EA_Window_InteractionRenownTacticAbility:GetSelectionCount()
    return self.m_SelectionCount
end

function EA_Window_InteractionRenownTacticAbility:IsSelectable()
    local advanceData = self:GetAdvanceData()
    
    return InteractionUtils.LessThanMaximumPurchaseCount( advanceData ) and
           (EA_Window_InteractionRenownTraining.GetPointsAvailable() >= advanceData.pointCost) and
           (EA_Window_InteractionRenownTraining.GetPointsSpent()     >= advanceData.minimumCategoryPoints)
end

function EA_Window_InteractionRenownTacticAbility:IsSelected()
    return (InteractionUtils.FindAdvance( self:GetAdvanceData(), EA_Window_InteractionRenownTraining.selectedAdvances ) ~= nil )
end

function EA_Window_InteractionRenownTacticAbility:UpdateState(pointsAvailable, pointsSpent)
    local advanceData = self:GetAdvanceData()
    
    if (self:IsSelected())
    then
        self:SetSelected()
    elseif (self.m_SelectionCount >= advanceData.maximumPurchaseCount)
    then
        self:SetPurchased()
    elseif (pointsAvailable <= 0) or (pointsAvailable < advanceData.pointCost) or (pointsSpent < advanceData.minimumCategoryPoints)
    then
        self:SetUnavailable()
    elseif (self.m_SelectionCount < advanceData.maximumPurchaseCount)
    then
        self:SetAvailable()
    else
        -- error, shouldn't reach here
    end
end

function EA_Window_InteractionRenownTacticAbility:Increment()
    self.m_SelectionCount = self.m_SelectionCount + 1
    
    local advanceData = self:GetAdvanceData()
    table.insert( EA_Window_InteractionRenownTraining.selectedAdvances, advanceData )
    EA_Window_InteractionRenownTraining.pointsSpent = EA_Window_InteractionRenownTraining.pointsSpent + advanceData.pointCost
    EA_Window_InteractionRenownTraining.UpdatePlayerResources()

    EA_Window_InteractionRenownTrainingLayout.RefreshStates()
end

function EA_Window_InteractionRenownTacticAbility:Decrement()
    self.m_SelectionCount = self.m_SelectionCount - 1

    local advanceData = self:GetAdvanceData()
    
    for index, data in ipairs(EA_Window_InteractionRenownTraining.selectedAdvances)
    do
        if ( (advanceData.category  == data.category) and
             (advanceData.tier      == data.tier)     and
             (advanceData.packageId == data.packageId) )
        then
            table.remove( EA_Window_InteractionRenownTraining.selectedAdvances, index )
            EA_Window_InteractionRenownTraining.pointsSpent = EA_Window_InteractionRenownTraining.pointsSpent - advanceData.pointCost
            EA_Window_InteractionRenownTraining.UpdatePlayerResources()
            break
        end
    end

    EA_Window_InteractionRenownTrainingLayout.RefreshStates()
end

----------------------------------------------------------------
-- Renown Passives Button Class
----------------------------------------------------------------
EA_Window_InteractionRenownPassive = Frame:Subclass("EA_Templates_RenownPassive")

function EA_Window_InteractionRenownPassive:Create(windowName, parentName, advancesTable)
    -- DEBUG(L"  Creating tactic frame "..StringToWString(windowName))
            
    local abilityFrame
    if (DoesWindowExist(windowName))
    then
        abilityFrame = FrameManager:Get(windowName)
    else
        abilityFrame = self:CreateFromTemplate(windowName, parentName)
    end

    if (abilityFrame ~= nil)
    then
        abilityFrame.m_AdvanceData     = advancesTable
        abilityFrame.m_SelectionCount  = 0

        local function DependencyChainSort(a, b)
            return InteractionUtils.GetDependencyChainLength( a, advancesTable ) < 
                   InteractionUtils.GetDependencyChainLength( b, advancesTable )
        end

        table.sort(abilityFrame.m_AdvanceData, DependencyChainSort)
    end
    
    local texture, x, y
    local advanceData = advancesTable[1]
    if (advanceData.abilityInfo)
    then
        texture, x, y = GetIconData(advanceData.abilityInfo.iconNum)
    else
        texture, x, y = GetIconData(advanceData.advanceIcon)
    end
       
    CircleImageSetTexture( windowName.."Icon", texture, 32, 32 )
    LabelSetText( windowName.."Level", L""..advanceData.timesPurchased )
    
    return abilityFrame
end

function EA_Window_InteractionRenownPassive:Reset()
    self.m_SelectionCount = 0
end

function EA_Window_InteractionRenownPassive:SetPurchased()
    ButtonSetDisabledFlag( self:GetName(), true )

    local color = DefaultColor.RowColors.SELECTED
    WindowSetTintColor( self:GetName().."Icon",       color.r, color.g, color.b )
    WindowSetTintColor( self:GetName().."Frame",      color.r, color.g, color.b )
    WindowSetTintColor( self:GetName().."LabelFrame", color.r, color.g, color.b )
end

function EA_Window_InteractionRenownPassive:SetAvailable()
    ButtonSetDisabledFlag( self:GetName(), false )

    local color = DefaultColor.RowColors.SELECTED
    WindowSetTintColor( self:GetName().."Icon",       color.r, color.g, color.b )
    WindowSetTintColor( self:GetName().."Frame",      color.r, color.g, color.b )
    WindowSetTintColor( self:GetName().."LabelFrame", color.r, color.g, color.b )
    
    local textColor = DefaultColor.RowColors.AVAILABLE
    LabelSetTextColor( self:GetName().."Level", textColor.r, textColor.g, textColor.b )
end

function EA_Window_InteractionRenownPassive:SetSelected()
    ButtonSetDisabledFlag( self:GetName(), false )

    local color = DefaultColor.RowColors.SELECTED
    WindowSetTintColor( self:GetName().."Icon",       color.r, color.g, color.b )
    WindowSetTintColor( self:GetName().."Frame",      color.r, color.g, color.b )
    WindowSetTintColor( self:GetName().."LabelFrame", color.r, color.g, color.b )

    local textColor = DefaultColor.RowColors.SELECTED
    LabelSetTextColor( self:GetName().."Level", textColor.r, textColor.g, textColor.b )
end

function EA_Window_InteractionRenownPassive:SetUnavailable()
    ButtonSetDisabledFlag( self:GetName(), true )
    
    local color = DefaultColor.RowColors.UNAVAILABLE
    WindowSetTintColor( self:GetName().."Icon",       color.r, color.g, color.b )
    WindowSetTintColor( self:GetName().."Frame",      color.r, color.g, color.b )
    WindowSetTintColor( self:GetName().."LabelFrame", color.r, color.g, color.b )

    local textColor = DefaultColor.RowColors.UNAVAILABLE
    LabelSetTextColor( self:GetName().."Level", textColor.r, textColor.g, textColor.b )
end

function EA_Window_InteractionRenownPassive:SetIcon()
    local texture, x, y = GetIconData(self.m_AdvanceData.abilityInfo.iconNum)
    CircleImageSetTexture(self:GetName().."Icon", texture, 32, 32)
end

function EA_Window_InteractionRenownPassive:GetAdvanceData()
    return self.m_AdvanceData[self:GetDisplayAdvanceIndex()]
end

function EA_Window_InteractionRenownPassive:GetDisplayAdvanceIndex()
    local advanceCount = #self.m_AdvanceData
    
    for index, data in ipairs(self.m_AdvanceData)
    do
        if InteractionUtils.LessThanMaximumPurchaseCount(data)
        then
            if (index + self.m_SelectionCount) <= advanceCount
            then
                -- DEBUG(L"  Purchased "..index + self.m_SelectionCount..L" / "..#self.m_AdvanceData)
                return index + self.m_SelectionCount
            else
                break
            end
        end
    end

    --DEBUG(L"  Detecting all advances purchased")
    
    -- otherwise everything is purchased so return the last item
    return advanceCount
end

function EA_Window_InteractionRenownPassive:GetCurrentAdvanceIndex()
    if (self.m_AdvanceData == nil)
    then
        return 0
    end
    
    for index, data in ipairs(self.m_AdvanceData)
    do
        if InteractionUtils.LessThanMaximumPurchaseCount(data)
        then
            -- DEBUG(L"  Purchased "..index..L" / "..#self.m_AdvanceData)
            return index - 1 -- the previous one was the last one purchased
        end
    end
    
    return #self.m_AdvanceData
end

function EA_Window_InteractionRenownPassive:GetSelectionCount()
    return self.m_SelectionCount
end

function EA_Window_InteractionRenownPassive:UpdateState(pointsAvailable, pointsSpent)
    local advanceData = self:GetAdvanceData()
    local labelWindow = self:GetName().."Level"
    
    if (self:IsSelectable())
    then
        self:SetAvailable()
    elseif (self:IsDeselectable())
    then
        self:SetSelected()
    elseif (pointsAvailable <= 0) or
           (pointsAvailable < advanceData.pointCost) or
           (pointsSpent < advanceData.minimumCategoryPoints)
    then
        self:SetUnavailable()
    elseif (self.m_SelectionCount >= advanceData.maximumPurchaseCount)
    then
        self:SetSelected()
    elseif InteractionUtils.LessThanMaximumPurchaseCount(advanceData)
    then
        self:SetAvailable()
    else
        -- error, shouldn't reach here
    end
    
    LabelSetText( labelWindow, L""..self:GetCurrentAdvanceIndex() + self.m_SelectionCount )
end

function EA_Window_InteractionRenownPassive:IsSelectable()
    local selectableAdvanceIndex = self:GetDisplayAdvanceIndex()
    
    return ((self:GetCurrentAdvanceIndex() + self.m_SelectionCount) < #self.m_AdvanceData) and
           (EA_Window_InteractionRenownTraining.GetPointsAvailable() >= self.m_AdvanceData[selectableAdvanceIndex].pointCost) and
           (EA_Window_InteractionRenownTraining.GetPointsSpent()     >= self.m_AdvanceData[selectableAdvanceIndex].minimumCategoryPoints)
end

function EA_Window_InteractionRenownPassive:IsDeselectable()
    return self.m_SelectionCount > 0
end

function EA_Window_InteractionRenownPassive:Increment()
    
    local advanceData = self.m_AdvanceData[self:GetDisplayAdvanceIndex()]
    table.insert( EA_Window_InteractionRenownTraining.selectedAdvances, advanceData )
    EA_Window_InteractionRenownTraining.pointsSpent = EA_Window_InteractionRenownTraining.pointsSpent + advanceData.pointCost
    EA_Window_InteractionRenownTraining.UpdatePlayerResources()

    self.m_SelectionCount = self.m_SelectionCount + 1

    EA_Window_InteractionRenownTrainingLayout.RefreshStates()
end

function EA_Window_InteractionRenownPassive:Decrement()
    self.m_SelectionCount = self.m_SelectionCount - 1

    local advanceData = self.m_AdvanceData[self:GetDisplayAdvanceIndex()]
    
    for index, data in ipairs(EA_Window_InteractionRenownTraining.selectedAdvances)
    do
        if ( (advanceData.category  == data.category) and
             (advanceData.tier      == data.tier)     and
             (advanceData.packageId == data.packageId) )
        then
            table.remove( EA_Window_InteractionRenownTraining.selectedAdvances, index )
            EA_Window_InteractionRenownTraining.pointsSpent = EA_Window_InteractionRenownTraining.pointsSpent - advanceData.pointCost
            EA_Window_InteractionRenownTraining.UpdatePlayerResources()
            break
        end
    end

    EA_Window_InteractionRenownTrainingLayout.RefreshStates()
end